from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser, PermissionsMixin
)
from django.utils.translation import gettext, gettext_lazy as _
from django.utils.safestring import mark_safe
from django.utils.crypto import get_random_string, salted_hmac
from django.contrib.auth import hashers
from django.conf import settings

hasher = getattr(hashers,settings.AUTH_HASHER)

# Create your models here.


class Customer(models.Model):
    '''客户信息表'''
    name = models.CharField(max_length=32, blank=True, null=True, verbose_name='客户姓名',default='')
    qq = models.CharField(max_length=64, unique=True, verbose_name='QQ')
    qq_name = models.CharField(max_length=64, blank=True, null=True, verbose_name='QQ名')
    phone = models.CharField(max_length=64, blank=True, null=True)
    id_card = models.CharField(max_length=64,blank=True,null=True,verbose_name='身份证')
    email = models.EmailField(max_length=64, blank=True, null=True, verbose_name='常用邮箱')
    source_choices = ((0, '转介绍'),
                      (1, 'qq群'),
                      (2, '官网'),
                      (3, '百度推广'),
                      (4, '51CTO'),
                      (5, '知乎'),
                      (6, '市场推广'))
    source = models.SmallIntegerField(choices=source_choices, verbose_name='客户来源')

    status_choices = ((0, '已报名'),
                      (1, '未报名'),
                      (2, '已退学'))
    status = models.SmallIntegerField(choices=status_choices, verbose_name='报名状态')
    refer_from = models.CharField(verbose_name='转介绍人qq', max_length=64, blank=True, null=True)
    consult_course = models.ForeignKey(to='Course', verbose_name='咨询课程', on_delete=models.CASCADE)
    content = models.TextField(verbose_name='咨询详情')
    consultant = models.ForeignKey('UserProfile', verbose_name='顾问', on_delete=models.CASCADE)
    memo = models.TextField(blank=True, null=True, verbose_name='备注')
    tags = models.ManyToManyField('Tag', blank=True, verbose_name='标签')
    date = models.DateTimeField(auto_now_add=True, verbose_name='录入时间')

    def __str__(self):
        if self.name:
            return self.name
        else:
            return self.qq

    class Meta:
        verbose_name_plural = '客户表'


class Tag(models.Model):
    '''标签'''
    name = models.CharField(unique=True, max_length=32)

    def __str__(self):
        return self.name
    
    class Meta:
        verbose_name_plural = '标签表'


class CustomerFollowUp(models.Model):
    '''客户跟进表'''
    customer = models.ForeignKey('Customer', verbose_name='客户', on_delete=models.CASCADE)
    content = models.TextField(verbose_name='跟进内容')
    consultant = models.ForeignKey('UserProfile', verbose_name='顾问', on_delete=models.CASCADE)
    intention_choices = ((0, '2周内报名'),
                         (1, '1个月内报名'),
                         (2, '近期无报名计划'),
                         (3, '已在其他机构报名'),
                         (4, '已报名'),
                         (5, '已拉黑'),)
    intention = models.SmallIntegerField(choices=intention_choices, verbose_name='报名意向')
    date = models.DateField(verbose_name='跟进时间', auto_now_add=True)

    def __str__(self):
        return '<内容 : %s>' %(self.intention)

    class Meta:
        verbose_name_plural = '客户跟进表'


class Course(models.Model):
    '''课程表'''
    name = models.CharField(max_length=64, unique=True)
    price = models.PositiveSmallIntegerField(verbose_name='价格')
    period = models.PositiveSmallIntegerField(verbose_name='周期(月)')
    outline = models.TextField(verbose_name='课程大纲')

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = '课程表'


class Branch(models.Model):
    '''校区'''
    name = models.CharField(max_length=128, unique=True, verbose_name='校名')
    addr = models.CharField(max_length=128, verbose_name='地址')

    class Meta:
        verbose_name_plural = '校区表'

    def __str__(self):
        return self.name


class ClassList(models.Model):
    '''班级表'''
    branch = models.ForeignKey(to='Branch', verbose_name='校区', on_delete=models.CASCADE)
    course = models.ForeignKey(to='Course', verbose_name='课程', on_delete=models.CASCADE)
    class_type_choices = ((0, '面授(脱产)'),
                          (1, '面授(周末)'),
                          (2, '网络班'))
    contract = models.ForeignKey('ContractTemplate',on_delete=models.CASCADE)
    class_type = models.SmallIntegerField(choices=class_type_choices, verbose_name='班级类型')
    semester = models.PositiveSmallIntegerField(verbose_name='学期')
    teachers = models.ManyToManyField(to="UserProfile")
    start_date = models.DateField(verbose_name='开班日期')
    end_date = models.DateField(verbose_name='结业日期', blank=True, null=True)

    def __str__(self):
        return '<课程名:%s; 学期:%s>' %(self.course.name, self.semester)

    class Meta:
        unique_together = ('branch', 'course', 'semester')
        verbose_name_plural = '班级表'


class CourseRecord(models.Model):
    '''上课记录表'''
    from_class = models.ForeignKey(to='ClassList', verbose_name='班级', on_delete=models.CASCADE)
    day_num = models.PositiveSmallIntegerField(verbose_name='第几节(天)')
    teacher = models.ForeignKey('UserProfile', verbose_name='讲课老师', on_delete=models.CASCADE)
    has_homework = models.BooleanField(default=True, verbose_name='是否有作业')
    homework_title = models.CharField(max_length=128, verbose_name='作业标题', blank=True, null=True)
    homework_content = models.TextField(verbose_name='作业内容', blank=True, null=True)
    outline = models.TextField(verbose_name='课程大纲')
    date = models.DateField(auto_now_add=True, verbose_name='上课日期')

    def __str__(self):
        return '<课程:%s，日期: %s>'%(self.from_class.course, self.day_num)

    class Meta:
        unique_together = ('from_class', 'day_num')
        verbose_name_plural = '上课记录表'


class StudyRecord(models.Model):
    '''学习记录表'''
    student = models.ForeignKey('Enrollment', verbose_name='学生', on_delete=models.CASCADE)
    course_record = models.ForeignKey('CourseRecord', verbose_name='上课记录', on_delete=models.CASCADE)
    attendance_choices = ((0,'已签到'),
                          (1, '迟到'),
                          (2, '缺勤'),
                          (3, '早退'),)
    attendance = models.SmallIntegerField(choices=attendance_choices, default=0, verbose_name='出席情况')

    score_choices = ((100, 'A+'),
                     (90, 'A'),
                     (85, 'B+'),
                     (75, 'B-'),
                     (70, 'C+'),
                     (60, 'C+'),
                     (40, 'C-'),
                     (-50, 'D'),
                     (-100, 'COPY'),
                     (0, 'N/A'),)
    score = models.SmallIntegerField(choices=score_choices, verbose_name='成绩')
    memo = models.TextField(blank=True, null=True, verbose_name='评语')
    date = models.DateField(auto_now_add=True)

    def __str__(self):
        return '<%s, 分数:%s>' %(self.course_record, self.score)


    class Meta:
        unique_together = ('student', 'course_record')
        verbose_name_plural = '学习记录表'


class Enrollment(models.Model):
    '''报名表'''
    customer = models.ForeignKey(to='Customer', on_delete=models.CASCADE, verbose_name='客户')
    enrolled_class = models.ForeignKey(to='ClassList', on_delete=models.CASCADE, verbose_name='所报班级')
    consultant = models.ForeignKey(to='UserProfile', on_delete=models.CASCADE, verbose_name='课程顾问')
    contract_agreed = models.BooleanField(default=False,verbose_name='学员是否同意')
    contract_approved = models.BooleanField(default=False, verbose_name='合同是否已审核')
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '%s'%(self.customer)

    class Meta:
        unique_together = ('customer', 'enrolled_class')
        verbose_name_plural = '报名表'


class Payment(models.Model):
    '''缴费记录'''
    customer = models.ForeignKey(to='Customer', on_delete=models.CASCADE)
    course = models.ForeignKey(to='Course', on_delete=models.CASCADE, verbose_name='所报课程')
    amount = models.PositiveIntegerField(verbose_name='金额', default=500)
    consultant = models.ForeignKey(to='UserProfile', blank=True, null=True, on_delete=models.SET_NULL)
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '%s %s'%(self.customer, self.amount)

    class Meta:
        verbose_name_plural = '缴费记录表'


class UserProfile(models.Model):
    '''账号'''
    email = models.EmailField(verbose_name='邮箱',max_length=255,unique=True)
    name = models.CharField(max_length=64,verbose_name='姓名')
    password = models.CharField(
                _('密码'),
                max_length=128,
                help_text=mark_safe("<a href=\"../password/\">修改密码</a>.")
            )
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    roles = models.ManyToManyField(to='Role', blank=True, verbose_name='角色')
    stu_account = models.OneToOneField('Customer',
                                    verbose_name='关联学员账号',
                                    blank=True,null=True,
                                    help_text='只有学员报名后才能开通',
                                    on_delete=models.CASCADE)
    permissions = models.ManyToManyField(to='Permission',blank=True)
    last_login = models.DateTimeField(auto_now=True)    # 必要字段，登录成功后，django会发送信号，更新该字段

    USERNAME_FIELD = 'email'    # 指定哪个字段作为登录的用户名
    PASSWORD_FIELD = 'password'    # 指定哪个密码作为密码字段
    REQUIRED_FIELDS = ['name',]    # 使用命令行创建用户时，除了用户名和密码外所需要的字段

    is_authenticated = True    # 是否登录
    is_anonymous = False

    def has_perm(self,perm):
        '''判断用户是否有权限'''
        res = False
        if self.is_admin:
            res = True
        elif self.roles.filter(permissions__name=perm).exists():
            res = True
        elif self.permissions.filter(name=perm).exists():
            res = True
        return res

    def set_password(self,new_password):
        '''更新密码'''
        self.password = hasher.encode(hasher,new_password,hasher.salt(hasher))

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = '账号表'

    def get_session_auth_hash(self):
        """
        必要函数，使用django的login方法要用到
        """
        key_salt = "django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash"
        return salted_hmac(key_salt, self.password).hexdigest()


class Role(models.Model):
    '''角色表'''
    name = models.CharField(max_length=32, unique=True, verbose_name='角色名')
    menus = models.ManyToManyField(to='Menu', blank=True)    # 角色可以访问哪些菜单
    permissions = models.ManyToManyField(to='Permission', blank=True)    # 角色拥有哪些权限

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = '角色表'


class Menu(models.Model):
    '''菜单表'''
    name = models.CharField(max_length=32)
    url_type_choices = ((0, '别名'),(1, '绝对路径'))
    url_type = models.SmallIntegerField(choices=url_type_choices, default=0)
    url_name = models.CharField(max_length=64, verbose_name='url名')

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = '菜单表'


class ContractTemplate(models.Model):
    '''合同模板'''
    name = models.CharField(verbose_name='合同名称',max_length=64,unique=True)
    template = models.TextField()

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = '合同表'


class Permission(models.Model):
    '''权限表'''
    name = models.CharField(max_length=64,unique=True,verbose_name='规则名')    # 权限名
    content = models.CharField(max_length=64,verbose_name='描述')

    def __str__(self):
        return self.content

    class Meta:
        verbose_name_plural = '权限表'